home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / xpaint-2.1.1 / rw / libpnmrw.c < prev    next >
C/C++ Source or Header  |  1995-06-21  |  29KB  |  1,383 lines

  1. /* libpnmrw.c - PBM/PGM/PPM read/write library
  2. **
  3. ** Copyright (C) 1988, 1989, 1991, 1992 by Jef Poskanzer.
  4. **
  5. ** Permission to use, copy, modify, and distribute this software and its
  6. ** documentation for any purpose and without fee is hereby granted, provided
  7. ** that the above copyright notice appear in all copies and that both that
  8. ** copyright notice and this permission notice appear in supporting
  9. ** documentation.  This software is provided "as is" without express or
  10. ** implied warranty.
  11. */
  12.  
  13. #if defined(SVR2) || defined(SVR3) || defined(SVR4)
  14. #ifndef SYSV
  15. #define SYSV
  16. #endif
  17. #endif
  18. #if ! ( defined(BSD) || defined(SYSV) || defined(MSDOS) )
  19. /* CONFIGURE: If your system is >= 4.2BSD, set the BSD option; if you're a
  20. ** System V site, set the SYSV option; and if you're IBM-compatible, set
  21. ** MSDOS.  If your compiler is ANSI C, you're probably better off setting
  22. ** SYSV - all it affects is string handling.
  23. */
  24. /* #define BSD */
  25. #define SYSV
  26. /* #define MSDOS */
  27. #endif
  28.  
  29. #include <stdio.h>
  30. #include "libpnmrw.h"
  31.  
  32. #ifdef SYSV
  33. #if !defined(sco)
  34. #include <string.h>
  35. #define rindex(s,c) strrchr(s,c)
  36. #endif
  37. #else /*SYSV*/
  38. #include <strings.h>
  39. #endif /*SYSV*/
  40.  
  41. void *malloc(int);
  42. void free(void *);
  43.  
  44.  
  45. /* Definitions. */
  46.  
  47. #define pbm_allocarray( cols, rows ) ((bit**) pm_allocarray( cols, rows, sizeof(bit) ))
  48. #define pbm_allocrow( cols ) ((bit*) pm_allocrow( cols, sizeof(bit) ))
  49. #define pbm_freearray( bits, rows ) pm_freearray( (char**) bits, rows )
  50. #define pbm_freerow( bitrow ) pm_freerow( (char*) bitrow )
  51. #define pgm_allocarray( cols, rows ) ((gray**) pm_allocarray( cols, rows, sizeof(gray) ))
  52. #define pgm_allocrow( cols ) ((gray*) pm_allocrow( cols, sizeof(gray) ))
  53. #define pgm_freearray( grays, rows ) pm_freearray( (char**) grays, rows )
  54. #define pgm_freerow( grayrow ) pm_freerow( (char*) grayrow )
  55. #define ppm_allocarray( cols, rows ) ((pixel**) pm_allocarray( cols, rows, sizeof(pixel) ))
  56. #define ppm_allocrow( cols ) ((pixel*) pm_allocrow( cols, sizeof(pixel) ))
  57. #define ppm_freearray( pixels, rows ) pm_freearray( (char**) pixels, rows )
  58. #define ppm_freerow( pixelrow ) pm_freerow( (char*) pixelrow )
  59.  
  60.  
  61. /* Variables. */
  62.  
  63. static char* progname;
  64.  
  65.  
  66. /* Variable-sized arrays. */
  67.  
  68. char*
  69. pm_allocrow( cols, size )
  70.     int cols;
  71.     int size;
  72.     {
  73.     register char* itrow;
  74.  
  75.     itrow = (char*) malloc( cols * size );
  76.     if ( itrow == (char*) 0 )
  77.     {
  78.     (void) fprintf(
  79.         stderr, "%s: out of memory allocating a row\n", progname );
  80.     return (char*) 0;
  81.     }
  82.     return itrow;
  83.     }
  84.  
  85. void
  86. pm_freerow( itrow )
  87.     char* itrow;
  88.     {
  89.     free( itrow );
  90.     }
  91.  
  92. char**
  93. pm_allocarray( cols, rows, size )
  94.     int cols, rows;
  95.     int size;
  96.     {
  97.     char** its;
  98.     int i;
  99.  
  100.     its = (char**) malloc( rows * sizeof(char*) );
  101.     if ( its == (char**) 0 )
  102.     {
  103.     (void) fprintf(
  104.         stderr, "%s: out of memory allocating an array\n", progname );
  105.     return (char**) 0;
  106.     }
  107.     its[0] = (char*) malloc( rows * cols * size );
  108.     if ( its[0] == (char*) 0 )
  109.     {
  110.     (void) fprintf(
  111.         stderr, "%s: out of memory allocating an array\n", progname );
  112.     free( (char*) its );
  113.     return (char**) 0;
  114.     }
  115.     for ( i = 1; i < rows; ++i )
  116.     its[i] = &(its[0][i * cols * size]);
  117.     return its;
  118.     }
  119.  
  120. void
  121. pm_freearray( its, rows )
  122.     char** its;
  123.     int rows;
  124.     {
  125.     free( its[0] );
  126.     free( its );
  127.     }
  128.  
  129.  
  130. /* File open/close that handles "-" as stdin and checks errors. */
  131.  
  132. static void
  133. pm_perror( reason )
  134.     char* reason;
  135.     {
  136.     extern char* sys_errlist[];
  137.     extern int errno;
  138.     char* e;
  139.  
  140.     e = sys_errlist[errno];
  141.  
  142.     if ( reason != 0 && reason[0] != '\0' )
  143.     (void) fprintf( stderr, "%s: %s - %s\n", progname, reason, e );
  144.     else
  145.     (void) fprintf( stderr, "%s: %s\n", progname, e );
  146.     }
  147.  
  148. FILE*
  149. pm_openr( name )
  150.     char* name;
  151.     {
  152.     FILE* f;
  153.  
  154.     if ( strcmp( name, "-" ) == 0 )
  155.     f = stdin;
  156.     else
  157.     {
  158. #ifdef MSDOS
  159.     f = fopen( name, "rb" );
  160. #else /*MSDOS*/
  161.     f = fopen( name, "r" );
  162. #endif /*MSDOS*/
  163.     if ( f == NULL )
  164.         {
  165.         pm_perror( name );
  166.         return (FILE*) 0;
  167.         }
  168.     }
  169.     return f;
  170.     }
  171.  
  172. FILE*
  173. pm_openw( name )
  174.     char* name;
  175.     {
  176.     FILE* f;
  177.  
  178. #ifdef MSDOS
  179.     f = fopen( name, "wb" );
  180. #else /*MSDOS*/
  181.     f = fopen( name, "w" );
  182. #endif /*MSDOS*/
  183.     if ( f == NULL )
  184.     {
  185.     pm_perror( name );
  186.     return (FILE*) 0;
  187.     }
  188.     return f;
  189.     }
  190.  
  191. int
  192. pm_closer( f )
  193.     FILE* f;
  194.     {
  195.     if ( ferror( f ) )
  196.     {
  197.     (void) fprintf(
  198.         stderr, "%s: a file read error occurred at some point\n",
  199.         progname );
  200.     return -1;
  201.     }
  202.     if ( f != stdin )
  203.     if ( fclose( f ) != 0 )
  204.         {
  205.         pm_perror( "fclose" );
  206.         return -1;
  207.         }
  208.     return 0;
  209.     }
  210.  
  211. int
  212. pm_closew( f )
  213.     FILE* f;
  214.     {
  215.     fflush( f );
  216.     if ( ferror( f ) )
  217.     {
  218.     (void) fprintf(
  219.         stderr, "%s: a file write error occurred at some point\n",
  220.         progname );
  221.     return -1;
  222.     }
  223.     if ( f != stdout )
  224.     if ( fclose( f ) != 0 )
  225.         {
  226.         pm_perror( "fclose" );
  227.         return -1;
  228.         }
  229.     return 0;
  230.     }
  231.  
  232. static int
  233. pbm_getc( file )
  234.     FILE* file;
  235.     {
  236.     register int ich;
  237.  
  238.     ich = getc( file );
  239.     if ( ich == EOF )
  240.     {
  241.     (void) fprintf( stderr, "%s: EOF / read error\n", progname );
  242.     return EOF;
  243.     }
  244.     
  245.     if ( ich == '#' )
  246.     {
  247.     do
  248.         {
  249.         ich = getc( file );
  250.         if ( ich == EOF )
  251.         {
  252.         (void) fprintf( stderr, "%s: EOF / read error\n", progname );
  253.         return EOF;
  254.         }
  255.         }
  256.     while ( ich != '\n' && ich != '\r' );
  257.     }
  258.  
  259.     return ich;
  260.     }
  261.  
  262. static bit
  263. pbm_getbit( file )
  264.     FILE* file;
  265.     {
  266.     register int ich;
  267.  
  268.     do
  269.     {
  270.     ich = pbm_getc( file );
  271.     if ( ich == EOF )
  272.         return -1;
  273.     }
  274.     while ( ich == ' ' || ich == '\t' || ich == '\n' || ich == '\r' );
  275.  
  276.     if ( ich != '0' && ich != '1' )
  277.     {
  278.     (void) fprintf(
  279.         stderr, "%s: junk in file where bits should be\n", progname );
  280.     return -1;
  281.     }
  282.  
  283.     return ( ich == '1' ) ? 1 : 0;
  284.     }
  285.  
  286. static int
  287. pbm_readmagicnumber( file )
  288.     FILE* file;
  289.     {
  290.     int ich1, ich2;
  291.  
  292.     ich1 = getc( file );
  293.     if ( ich1 == EOF )
  294.     {
  295.     (void) fprintf(
  296.         stderr, "%s: EOF / read error reading magic number\n", progname );
  297.     return -1;
  298.     }
  299.     ich2 = getc( file );
  300.     if ( ich2 == EOF )
  301.     {
  302.     (void) fprintf(
  303.         stderr, "%s: EOF / read error reading magic number\n", progname );
  304.     return -1;
  305.     }
  306.     return ich1 * 256 + ich2;
  307.     }
  308.  
  309. static int
  310. pbm_getint( file )
  311.     FILE* file;
  312.     {
  313.     register char ich;
  314.     register int i;
  315.  
  316.     do
  317.     {
  318.     ich = pbm_getc( file );
  319.     if ( ich == EOF )
  320.         return -1;
  321.     }
  322.     while ( ich == ' ' || ich == '\t' || ich == '\n' || ich == '\r' );
  323.  
  324.     if ( ich < '0' || ich > '9' )
  325.     {
  326.     (void) fprintf(
  327.         stderr, "%s: junk in file where an integer should be\n", progname );
  328.     return -1;
  329.     }
  330.  
  331.     i = 0;
  332.     do
  333.     {
  334.     i = i * 10 + ich - '0';
  335.     ich = pbm_getc( file );
  336.     if ( ich == EOF )
  337.         return -1;
  338.         }
  339.     while ( ich >= '0' && ich <= '9' );
  340.  
  341.     return i;
  342.     }
  343.  
  344. static int
  345. pbm_readpbminitrest( file, colsP, rowsP )
  346.     FILE* file;
  347.     int* colsP;
  348.     int* rowsP;
  349.     {
  350.     /* Read size. */
  351.     *colsP = pbm_getint( file );
  352.     *rowsP = pbm_getint( file );
  353.     if ( *colsP == -1 || *rowsP == -1 )
  354.     return -1;
  355.     return 0;
  356.     }
  357.  
  358. static int
  359. pbm_getrawbyte( file )
  360.     FILE* file;
  361.     {
  362.     register int iby;
  363.  
  364.     iby = getc( file );
  365.     if ( iby == EOF )
  366.     {
  367.     (void) fprintf( stderr, "%s: EOF / read error\n", progname );
  368.     return -1;
  369.     }
  370.     return iby;
  371.     }
  372.  
  373. static int
  374. pbm_readpbmrow( file, bitrow, cols, format )
  375.     FILE* file;
  376.     bit* bitrow;
  377.     int cols, format;
  378.     {
  379.     register int col, bitshift, b;
  380.     register int item;
  381.     register bit* bP;
  382.  
  383.     switch ( format )
  384.     {
  385.     case PBM_FORMAT:
  386.     for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
  387.         {
  388.         b = pbm_getbit( file );
  389.         if ( b == -1 )
  390.         return -1;
  391.         *bP = b;
  392.         }
  393.     break;
  394.  
  395.     case RPBM_FORMAT:
  396.     bitshift = -1;
  397.     for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
  398.         {
  399.         if ( bitshift == -1 )
  400.         {
  401.         item = pbm_getrawbyte( file );
  402.         if ( item == -1 )
  403.             return -1;
  404.         bitshift = 7;
  405.         }
  406.         *bP = ( item >> bitshift ) & 1;
  407.         --bitshift;
  408.         }
  409.     break;
  410.  
  411.     default:
  412.     (void) fprintf( stderr, "%s: can't happen\n", progname );
  413.     return -1;
  414.     }
  415.     return 0;
  416.     }
  417.  
  418. static void
  419. pbm_writepbminit( file, cols, rows, forceplain )
  420.     FILE* file;
  421.     int cols, rows;
  422.     int forceplain;
  423.     {
  424.     if ( ! forceplain )
  425.     (void) fprintf(
  426.         file, "%c%c\n%d %d\n", PBM_MAGIC1, RPBM_MAGIC2, cols, rows );
  427.     else
  428.     (void) fprintf(
  429.         file, "%c%c\n%d %d\n", PBM_MAGIC1, PBM_MAGIC2, cols, rows );
  430.     }
  431.  
  432. static void
  433. pbm_writepbmrowraw( file, bitrow, cols )
  434.     FILE* file;
  435.     bit* bitrow;
  436.     int cols;
  437.     {
  438.     register int col, bitshift;
  439.     register unsigned char item;
  440.     register bit* bP;
  441.  
  442.     bitshift = 7;
  443.     item = 0;
  444.     for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
  445.     {
  446.     if ( *bP )
  447.         item += 1 << bitshift;
  448.     --bitshift;
  449.     if ( bitshift == -1 )
  450.         {
  451.         (void) putc( item, file );
  452.         bitshift = 7;
  453.         item = 0;
  454.         }
  455.     }
  456.     if ( bitshift != 7 )
  457.     (void) putc( item, file );
  458.     }
  459.  
  460. static void
  461. pbm_writepbmrowplain( file, bitrow, cols )
  462.     FILE* file;
  463.     bit* bitrow;
  464.     int cols;
  465.     {
  466.     register int col, charcount;
  467.     register bit* bP;
  468.  
  469.     charcount = 0;
  470.     for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
  471.     {
  472.     if ( charcount >= 70 )
  473.         {
  474.         (void) putc( '\n', file );
  475.         charcount = 0;
  476.         }
  477.     putc( *bP ? '1' : '0', file );
  478.     ++charcount;
  479.     }
  480.     (void) putc( '\n', file );
  481.     }
  482.  
  483. static void
  484. pbm_writepbmrow( file, bitrow, cols, forceplain )
  485.     FILE* file;
  486.     bit* bitrow;
  487.     int cols;
  488.     int forceplain;
  489.     {
  490.     if ( ! forceplain )
  491.     pbm_writepbmrowraw( file, bitrow, cols );
  492.     else
  493.     pbm_writepbmrowplain( file, bitrow, cols );
  494.     }
  495.  
  496. static int
  497. pgm_readpgminitrest( file, colsP, rowsP, maxvalP )
  498.     FILE* file;
  499.     int* colsP;
  500.     int* rowsP;
  501.     gray* maxvalP;
  502.     {
  503.     int maxval;
  504.  
  505.     /* Read size. */
  506.     *colsP = pbm_getint( file );
  507.     *rowsP = pbm_getint( file );
  508.     if ( *colsP == -1 || *rowsP == -1 )
  509.     return -1;
  510.  
  511.     /* Read maxval. */
  512.     maxval = pbm_getint( file );
  513.     if ( maxval == -1 )
  514.     return -1;
  515.     if ( maxval > PGM_MAXMAXVAL )
  516.     {
  517.     (void) fprintf( stderr, "%s: maxval is too large\n", progname );
  518.     return -1;
  519.     }
  520.     *maxvalP = maxval;
  521.     return 0;
  522.     }
  523.  
  524. #if __STDC__
  525. static int
  526. pgm_readpgmrow( FILE* file, gray* grayrow, int cols, gray maxval, int format )
  527. #else /*__STDC__*/
  528. static int
  529. pgm_readpgmrow( file, grayrow, cols, maxval, format )
  530.     FILE* file;
  531.     gray* grayrow;
  532.     int cols;
  533.     gray maxval;
  534.     int format;
  535. #endif /*__STDC__*/
  536.     {
  537.     register int col, val;
  538.     register gray* gP;
  539.  
  540.     switch ( format )
  541.     {
  542.     case PGM_FORMAT:
  543.     for ( col = 0, gP = grayrow; col < cols; ++col, ++gP )
  544.         {
  545.         val = pbm_getint( file );
  546.         if ( val == -1 )
  547.         return -1;
  548.         *gP = val;
  549.         }
  550.     break;
  551.     
  552.     case RPGM_FORMAT:
  553.     if ( fread( grayrow, 1, cols, file ) != cols )
  554.         {
  555.         (void) fprintf( stderr, "%s: EOF / read error\n", progname );
  556.         return -1;
  557.         }
  558.     break;
  559.  
  560.     default:
  561.     (void) fprintf( stderr, "%s: can't happen\n", progname );
  562.     return -1;
  563.     }
  564.     return 0;
  565.     }
  566.  
  567. #if __STDC__
  568. static void
  569. pgm_writepgminit( FILE* file, int cols, int rows, gray maxval, int forceplain )
  570. #else /*__STDC__*/
  571. static void
  572. pgm_writepgminit( file, cols, rows, maxval, forceplain )
  573.     FILE* file;
  574.     int cols, rows;
  575.     gray maxval;
  576.     int forceplain;
  577. #endif /*__STDC__*/
  578.     {
  579.     if ( maxval <= 255 && ! forceplain )
  580.     fprintf(
  581.         file, "%c%c\n%d %d\n%d\n", PGM_MAGIC1, RPGM_MAGIC2,
  582.         cols, rows, maxval );
  583.     else
  584.     fprintf(
  585.         file, "%c%c\n%d %d\n%d\n", PGM_MAGIC1, PGM_MAGIC2,
  586.         cols, rows, maxval );
  587.     }
  588.  
  589. static void
  590. putus( n, file )
  591.     unsigned short n;
  592.     FILE* file;
  593.     {
  594.     if ( n >= 10 )
  595.     putus( n / 10, file );
  596.     putc( n % 10 + '0', file );
  597.     }
  598.  
  599. static int
  600. pgm_writepgmrowraw( file, grayrow, cols, maxval )
  601.     FILE* file;
  602.     gray* grayrow;
  603.     int cols;
  604.     gray maxval;
  605.     {
  606.     if ( fwrite( grayrow, 1, cols, file ) != cols )
  607.     {
  608.     (void) fprintf( stderr, "%s: write error\n", progname );
  609.     return -1;
  610.     }
  611.     return 0;
  612.     }
  613.  
  614. static int
  615. pgm_writepgmrowplain( file, grayrow, cols, maxval )
  616.     FILE* file;
  617.     gray* grayrow;
  618.     int cols;
  619.     gray maxval;
  620.     {
  621.     register int col, charcount;
  622.     register gray* gP;
  623.  
  624.     charcount = 0;
  625.     for ( col = 0, gP = grayrow; col < cols; ++col, ++gP )
  626.     {
  627.     if ( charcount >= 65 )
  628.         {
  629.         (void) putc( '\n', file );
  630.         charcount = 0;
  631.         }
  632.     else if ( charcount > 0 )
  633.         {
  634.         (void) putc( ' ', file );
  635.         ++charcount;
  636.         }
  637.     putus( (unsigned short) *gP, file );
  638.     charcount += 3;
  639.     }
  640.     if ( charcount > 0 )
  641.     (void) putc( '\n', file );
  642.     return 0;
  643.     }
  644.  
  645. #if __STDC__
  646. static int
  647. pgm_writepgmrow( FILE* file, gray* grayrow, int cols, gray maxval, int forceplain )
  648. #else /*__STDC__*/
  649. static int
  650. pgm_writepgmrow( file, grayrow, cols, maxval, forceplain )
  651.     FILE* file;
  652.     gray* grayrow;
  653.     int cols;
  654.     gray maxval;
  655.     int forceplain;
  656. #endif /*__STDC__*/
  657.     {
  658.     if ( maxval <= 255 && ! forceplain )
  659.     return pgm_writepgmrowraw( file, grayrow, cols, maxval );
  660.     else
  661.     return pgm_writepgmrowplain( file, grayrow, cols, maxval );
  662.     }
  663.  
  664. static int
  665. ppm_readppminitrest( file, colsP, rowsP, maxvalP )
  666.     FILE* file;
  667.     int* colsP;
  668.     int* rowsP;
  669.     pixval* maxvalP;
  670.     {
  671.     int maxval;
  672.  
  673.     /* Read size. */
  674.     *colsP = pbm_getint( file );
  675.     *rowsP = pbm_getint( file );
  676.     if ( *colsP == -1 || *rowsP == -1 )
  677.     return -1;
  678.  
  679.     /* Read maxval. */
  680.     maxval = pbm_getint( file );
  681.     if ( maxval == -1 )
  682.     return -1;
  683.     if ( maxval > PPM_MAXMAXVAL )
  684.     {
  685.     (void) fprintf( stderr, "%s: maxval is too large\n", progname );
  686.     return -1;
  687.     }
  688.     *maxvalP = maxval;
  689.     return 0;
  690.     }
  691.  
  692. #if __STDC__
  693. static int
  694. ppm_readppmrow( FILE* file, pixel* pixelrow, int cols, pixval maxval, int format )
  695. #else /*__STDC__*/
  696. static int
  697. ppm_readppmrow( file, pixelrow, cols, maxval, format )
  698.     FILE* file;
  699.     pixel* pixelrow;
  700.     int cols, format;
  701.     pixval maxval;
  702. #endif /*__STDC__*/
  703.     {
  704.     register int col;
  705.     register pixel* pP;
  706.     register int r, g, b;
  707.     gray* grayrow;
  708.     register gray* gP;
  709.  
  710.     switch ( format )
  711.     {
  712.     case PPM_FORMAT:
  713.     for ( col = 0, pP = pixelrow; col < cols; ++col, ++pP )
  714.         {
  715.         r = pbm_getint( file );
  716.         g = pbm_getint( file );
  717.         b = pbm_getint( file );
  718.         if ( r == -1 || g == -1 || b == -1 )
  719.         return -1;
  720.         PPM_ASSIGN( *pP, r, g, b );
  721.         }
  722.     break;
  723.  
  724.     case RPPM_FORMAT:
  725.     grayrow = pgm_allocrow( 3 * cols );
  726.     if ( grayrow == (gray*) 0 )
  727.         return -1;
  728.     if ( fread( grayrow, 1, 3 * cols, file ) != 3 * cols )
  729.         {
  730.         (void) fprintf( stderr, "%s: EOF / read error\n", progname );
  731.         return -1;
  732.         }
  733.     for ( col = 0, gP = grayrow, pP = pixelrow; col < cols; ++col, ++pP )
  734.         {
  735.         r = *gP++;
  736.         g = *gP++;
  737.         b = *gP++;
  738.         PPM_ASSIGN( *pP, r, g, b );
  739.         }
  740.     pgm_freerow( grayrow );
  741.     break;
  742.  
  743.     default:
  744.     (void) fprintf( stderr, "%s: can't happen\n", progname );
  745.     return -1;
  746.     }
  747.     return 0;
  748.     }
  749.  
  750. #if __STDC__
  751. static void
  752. ppm_writeppminit( FILE* file, int cols, int rows, pixval maxval, int forceplain )
  753. #else /*__STDC__*/
  754. static void
  755. ppm_writeppminit( file, cols, rows, maxval, forceplain )
  756.     FILE* file;
  757.     int cols, rows;
  758.     pixval maxval;
  759.     int forceplain;
  760. #endif /*__STDC__*/
  761.     {
  762.     if ( maxval <= 255 && ! forceplain )
  763.     fprintf(
  764.         file, "%c%c\n%d %d\n%d\n", PPM_MAGIC1, RPPM_MAGIC2,
  765.         cols, rows, maxval );
  766.     else
  767.     fprintf(
  768.         file, "%c%c\n%d %d\n%d\n", PPM_MAGIC1, PPM_MAGIC2,
  769.         cols, rows, maxval );
  770.     }
  771.  
  772. static int
  773. ppm_writeppmrowraw( file, pixelrow, cols, maxval )
  774.     FILE* file;
  775.     pixel* pixelrow;
  776.     int cols;
  777.     pixval maxval;
  778.     {
  779.     register int col;
  780.     register pixel* pP;
  781.     gray* grayrow;
  782.     register gray* gP;
  783.  
  784.     grayrow = pgm_allocrow( 3 * cols );
  785.     if ( grayrow == (gray*) 0 )
  786.     return -1;
  787.     for ( col = 0, pP = pixelrow, gP = grayrow; col < cols; ++col, ++pP )
  788.     {
  789.     *gP++ = PPM_GETR( *pP );
  790.     *gP++ = PPM_GETG( *pP );
  791.     *gP++ = PPM_GETB( *pP );
  792.         }
  793.     if ( fwrite( grayrow, 1, 3 * cols, file ) != 3 * cols )
  794.     {
  795.     (void) fprintf( stderr, "%s: write error\n", progname );
  796.     return -1;
  797.     }
  798.     pgm_freerow( grayrow );
  799.     return 0;
  800.     }
  801.  
  802. static int
  803. ppm_writeppmrowplain( file, pixelrow, cols, maxval )
  804.     FILE* file;
  805.     pixel* pixelrow;
  806.     int cols;
  807.     pixval maxval;
  808.     {
  809.     register int col, charcount;
  810.     register pixel* pP;
  811.     register pixval val;
  812.  
  813.     charcount = 0;
  814.     for ( col = 0, pP = pixelrow; col < cols; ++col, ++pP )
  815.     {
  816.     if ( charcount >= 65 )
  817.         {
  818.         (void) putc( '\n', file );
  819.         charcount = 0;
  820.         }
  821.     else if ( charcount > 0 )
  822.         {
  823.         (void) putc( ' ', file );
  824.         (void) putc( ' ', file );
  825.         charcount += 2;
  826.         }
  827.     val = PPM_GETR( *pP );
  828.     putus( val, file );
  829.     (void) putc( ' ', file );
  830.     val = PPM_GETG( *pP );
  831.     putus( val, file );
  832.     (void) putc( ' ', file );
  833.     val = PPM_GETB( *pP );
  834.     putus( val, file );
  835.     charcount += 11;
  836.     }
  837.     if ( charcount > 0 )
  838.     (void) putc( '\n', file );
  839.     return 0;
  840.     }
  841.  
  842. #if __STDC__
  843. static int
  844. ppm_writeppmrow( FILE* file, pixel* pixelrow, int cols, pixval maxval, int forceplain )
  845. #else /*__STDC__*/
  846. static int
  847. ppm_writeppmrow( file, pixelrow, cols, maxval, forceplain )
  848.     FILE* file;
  849.     pixel* pixelrow;
  850.     int cols;
  851.     pixval maxval;
  852.     int forceplain;
  853. #endif /*__STDC__*/
  854.     {
  855.     if ( maxval <= 255 && ! forceplain )
  856.     return ppm_writeppmrowraw( file, pixelrow, cols, maxval );
  857.     else
  858.     return ppm_writeppmrowplain( file, pixelrow, cols, maxval );
  859.     }
  860.  
  861. void
  862. pnm_init2( pn )
  863.     char* pn;
  864.     {
  865.     /* Save program name. */
  866.     progname = pn;
  867.     }
  868.  
  869. xelval pnm_pbmmaxval = 1;
  870.  
  871. int
  872. pnm_readpnminit( file, colsP, rowsP, maxvalP, formatP )
  873.     FILE* file;
  874.     int* colsP;
  875.     int* rowsP;
  876.     int* formatP;
  877.     xelval* maxvalP;
  878.     {
  879.     gray gmaxval;
  880.  
  881.     /* Check magic number. */
  882.     *formatP = pbm_readmagicnumber( file );
  883.     if ( *formatP == -1 )
  884.     return -1;
  885.     switch ( PNM_FORMAT_TYPE(*formatP) )
  886.     {
  887.     case PPM_TYPE:
  888.     if ( ppm_readppminitrest( file, colsP, rowsP, (pixval*) maxvalP ) < 0 )
  889.         return -1;
  890.     break;
  891.  
  892.     case PGM_TYPE:
  893.     if ( pgm_readpgminitrest( file, colsP, rowsP, &gmaxval ) < 0 )
  894.         return -1;
  895.     *maxvalP = (xelval) gmaxval;
  896.     break;
  897.  
  898.     case PBM_TYPE:
  899.     if ( pbm_readpbminitrest( file, colsP, rowsP ) < 0 )
  900.         return -1;
  901.     *maxvalP = pnm_pbmmaxval;
  902.     break;
  903.  
  904.     default:
  905.     (void) fprintf(
  906.         stderr, "%s: bad magic number - not a ppm, pgm, or pbm file\n",
  907.         progname );
  908.     return -1;
  909.     }
  910.     return 0;
  911.     }
  912.  
  913. #if __STDC__
  914. int
  915. pnm_readpnmrow( FILE* file, xel* xelrow, int cols, xelval maxval, int format )
  916. #else /*__STDC__*/
  917. int
  918. pnm_readpnmrow( file, xelrow, cols, maxval, format )
  919.     FILE* file;
  920.     xel* xelrow;
  921.     xelval maxval;
  922.     int cols, format;
  923. #endif /*__STDC__*/
  924.     {
  925.     register int col;
  926.     register xel* xP;
  927.     gray* grayrow;
  928.     register gray* gP;
  929.     bit* bitrow;
  930.     register bit* bP;
  931.  
  932.     switch ( PNM_FORMAT_TYPE(format) )
  933.     {
  934.     case PPM_TYPE:
  935.     if ( ppm_readppmrow( file, (pixel*) xelrow, cols, (pixval) maxval, format ) < 0 )
  936.         return -1;
  937.     break;
  938.  
  939.     case PGM_TYPE:
  940.     grayrow = pgm_allocrow( cols );
  941.     if ( grayrow == (gray*) 0 )
  942.         return -1;
  943.     if ( pgm_readpgmrow( file, grayrow, cols, (gray) maxval, format ) < 0 )
  944.         return -1;
  945.     for ( col = 0, xP = xelrow, gP = grayrow; col < cols; ++col, ++xP, ++gP )
  946.         PNM_ASSIGN1( *xP, *gP );
  947.     pgm_freerow( grayrow );
  948.     break;
  949.  
  950.     case PBM_TYPE:
  951.     bitrow = pbm_allocrow( cols );
  952.     if ( bitrow == (bit*) 0 )
  953.         return -1;
  954.     if ( pbm_readpbmrow( file, bitrow, cols, format ) < 0 )
  955.         {
  956.         pbm_freerow( bitrow );
  957.         return -1;
  958.         }
  959.     for ( col = 0, xP = xelrow, bP = bitrow; col < cols; ++col, ++xP, ++bP )
  960.         PNM_ASSIGN1( *xP, *bP == PBM_BLACK ? 0: pnm_pbmmaxval );
  961.     pbm_freerow( bitrow );
  962.     break;
  963.  
  964.     default:
  965.     (void) fprintf( stderr, "%s: can't happen\n", progname );
  966.     return -1;
  967.     }
  968.     return 0;
  969.     }
  970.  
  971. xel**
  972. pnm_readpnm( file, colsP, rowsP, maxvalP, formatP )
  973.     FILE* file;
  974.     int* colsP;
  975.     int* rowsP;
  976.     int* formatP;
  977.     xelval* maxvalP;
  978.     {
  979.     xel** xels;
  980.     int row;
  981.  
  982.     if ( pnm_readpnminit( file, colsP, rowsP, maxvalP, formatP ) < 0 )
  983.     return (xel**) 0;
  984.  
  985.     xels = pnm_allocarray( *colsP, *rowsP );
  986.     if ( xels == (xel**) 0 )
  987.     return (xel**) 0;
  988.  
  989.     for ( row = 0; row < *rowsP; ++row )
  990.     if ( pnm_readpnmrow( file, xels[row], *colsP, *maxvalP, *formatP ) < 0 )
  991.         {
  992.         pnm_freearray( xels, *rowsP );
  993.         return (xel**) 0;
  994.         }
  995.  
  996.     return xels;
  997.     }
  998.  
  999. #if __STDC__
  1000. int
  1001. pnm_writepnminit( FILE* file, int cols, int rows, xelval maxval, int format, int forceplain )
  1002. #else /*__STDC__*/
  1003. int
  1004. pnm_writepnminit( file, cols, rows, maxval, format, forceplain )
  1005.     FILE* file;
  1006.     int cols, rows, format;
  1007.     xelval maxval;
  1008.     int forceplain;
  1009. #endif /*__STDC__*/
  1010.     {
  1011.     switch ( PNM_FORMAT_TYPE(format) )
  1012.     {
  1013.     case PPM_TYPE:
  1014.     ppm_writeppminit( file, cols, rows, (pixval) maxval, forceplain );
  1015.     break;
  1016.  
  1017.     case PGM_TYPE:
  1018.     pgm_writepgminit( file, cols, rows, (gray) maxval, forceplain );
  1019.     break;
  1020.  
  1021.     case PBM_TYPE:
  1022.     pbm_writepbminit( file, cols, rows, forceplain );
  1023.     break;
  1024.  
  1025.     default:
  1026.     (void) fprintf( stderr, "%s: can't happen\n", progname );
  1027.     return -1;
  1028.     }
  1029.     return 0;
  1030.     }
  1031.  
  1032. #if __STDC__
  1033. int
  1034. pnm_writepnmrow( FILE* file, xel* xelrow, int cols, xelval maxval, int format, int forceplain )
  1035. #else /*__STDC__*/
  1036. int
  1037. pnm_writepnmrow( file, xelrow, cols, maxval, format, forceplain )
  1038.     FILE* file;
  1039.     xel* xelrow;
  1040.     int cols, format;
  1041.     xelval maxval;
  1042.     int forceplain;
  1043. #endif /*__STDC__*/
  1044.     {
  1045.     register int col;
  1046.     register xel* xP;
  1047.     gray* grayrow;
  1048.     register gray* gP;
  1049.     bit* bitrow;
  1050.     register bit* bP;
  1051.  
  1052.     switch ( PNM_FORMAT_TYPE(format) )
  1053.     {
  1054.     case PPM_TYPE:
  1055.     if ( ppm_writeppmrow( file, (pixel*) xelrow, cols, (pixval) maxval, forceplain ) < 0 )
  1056.         return -1;
  1057.     break;
  1058.  
  1059.     case PGM_TYPE:
  1060.     grayrow = pgm_allocrow( cols );
  1061.     if ( grayrow == (gray*) 0 )
  1062.         return -1;
  1063.     for ( col = 0, gP = grayrow, xP = xelrow; col < cols; ++col, ++gP, ++xP )
  1064.         *gP = PNM_GET1( *xP );
  1065.     if ( pgm_writepgmrow( file, grayrow, cols, (gray) maxval, forceplain ) < 0 )
  1066.         {
  1067.         pgm_freerow( grayrow );
  1068.         return -1;
  1069.         }
  1070.     pgm_freerow( grayrow );
  1071.     break;
  1072.  
  1073.     case PBM_TYPE:
  1074.     bitrow = pbm_allocrow( cols );
  1075.     if ( bitrow == (bit*) 0 )
  1076.         return -1;
  1077.     for ( col = 0, bP = bitrow, xP = xelrow; col < cols; ++col, ++bP, ++xP )
  1078.         *bP = PNM_GET1( *xP ) == 0 ? PBM_BLACK : PBM_WHITE;
  1079.     pbm_writepbmrow( file, bitrow, cols, forceplain );
  1080.     pbm_freerow( bitrow );
  1081.     break;
  1082.  
  1083.     default:
  1084.     (void) fprintf( stderr, "%s: can't happen\n", progname );
  1085.     return -1;
  1086.     }
  1087.     return 0;
  1088.     }
  1089.  
  1090. #if __STDC__
  1091. int
  1092. pnm_writepnm( FILE* file, xel** xels, int cols, int rows, xelval maxval, int format, int forceplain )
  1093. #else /*__STDC__*/
  1094. int
  1095. pnm_writepnm( file, xels, cols, rows, maxval, format, forceplain )
  1096.     FILE* file;
  1097.     xel** xels;
  1098.     xelval maxval;
  1099.     int cols, rows, format;
  1100.     int forceplain;
  1101. #endif /*__STDC__*/
  1102.     {
  1103.     int row;
  1104.  
  1105.     if ( pnm_writepnminit( file, cols, rows, maxval, format, forceplain ) < 0 )
  1106.     return -1;
  1107.  
  1108.     for ( row = 0; row < rows; ++row )
  1109.     if ( pnm_writepnmrow( file, xels[row], cols, maxval, format, forceplain ) < 0 )
  1110.         return -1;
  1111.     return 0;
  1112.     }
  1113.  
  1114.  
  1115. /* Colormap stuff. */
  1116.  
  1117. #define HASH_SIZE 20023
  1118.  
  1119. #define ppm_hashpixel(p) ( ( ( (long) PPM_GETR(p) * 33023 + (long) PPM_GETG(p) * 30013 + (long) PPM_GETB(p) * 27011 ) & 0x7fffffff ) % HASH_SIZE )
  1120.  
  1121. colorhist_vector
  1122. ppm_computecolorhist( pixels, cols, rows, maxcolors, colorsP )
  1123.     pixel** pixels;
  1124.     int cols, rows, maxcolors;
  1125.     int* colorsP;
  1126.     {
  1127.     colorhash_table cht;
  1128.     colorhist_vector chv;
  1129.  
  1130.     cht = ppm_computecolorhash( pixels, cols, rows, maxcolors, colorsP );
  1131.     if ( cht == (colorhash_table) 0 )
  1132.     return (colorhist_vector) 0;
  1133.     chv = ppm_colorhashtocolorhist( cht, maxcolors );
  1134.     ppm_freecolorhash( cht );
  1135.     return chv;
  1136.     }
  1137.  
  1138. void
  1139. ppm_addtocolorhist( chv, colorsP, maxcolors, colorP, value, position )
  1140.     colorhist_vector chv;
  1141.     pixel* colorP;
  1142.     int* colorsP;
  1143.     int maxcolors, value, position;
  1144.     {
  1145.     int i, j;
  1146.  
  1147.     /* Search colorhist for the color. */
  1148.     for ( i = 0; i < *colorsP; ++i )
  1149.     if ( PPM_EQUAL( chv[i].color, *colorP ) )
  1150.         {
  1151.         /* Found it - move to new slot. */
  1152.         if ( position > i )
  1153.         {
  1154.         for ( j = i; j < position; ++j )
  1155.             chv[j] = chv[j + 1];
  1156.         }
  1157.         else if ( position < i )
  1158.         {
  1159.         for ( j = i; j > position; --j )
  1160.             chv[j] = chv[j - 1];
  1161.         }
  1162.         chv[position].color = *colorP;
  1163.         chv[position].value = value;
  1164.         return;
  1165.         }
  1166.     if ( *colorsP < maxcolors )
  1167.     {
  1168.     /* Didn't find it, but there's room to add it; so do so. */
  1169.     for ( i = *colorsP; i > position; --i )
  1170.         chv[i] = chv[i - 1];
  1171.     chv[position].color = *colorP;
  1172.     chv[position].value = value;
  1173.     ++(*colorsP);
  1174.     }
  1175.     }
  1176.  
  1177. colorhash_table
  1178. ppm_computecolorhash( pixels, cols, rows, maxcolors, colorsP )
  1179.     pixel** pixels;
  1180.     int cols, rows, maxcolors;
  1181.     int* colorsP;
  1182.     {
  1183.     colorhash_table cht;
  1184.     register pixel* pP;
  1185.     colorhist_list chl;
  1186.     int col, row, hash;
  1187.  
  1188.     cht = ppm_alloccolorhash( );
  1189.     if ( cht == (colorhash_table) 0 )
  1190.     return (colorhash_table) 0;
  1191.     *colorsP = 0;
  1192.  
  1193.     /* Go through the entire image, building a hash table of colors. */
  1194.     for ( row = 0; row < rows; ++row )
  1195.     for ( col = 0, pP = pixels[row]; col < cols; ++col, ++pP )
  1196.         {
  1197.         hash = ppm_hashpixel( *pP );
  1198.         for ( chl = cht[hash]; chl != (colorhist_list) 0; chl = chl->next )
  1199.         if ( PPM_EQUAL( chl->ch.color, *pP ) )
  1200.             break;
  1201.         if ( chl != (colorhist_list) 0 )
  1202.         ++(chl->ch.value);
  1203.         else
  1204.         {
  1205.         if ( ++(*colorsP) > maxcolors )
  1206.             {
  1207.             ppm_freecolorhash( cht );
  1208.             return (colorhash_table) 0;
  1209.             }
  1210.         chl = (colorhist_list) malloc( sizeof(struct colorhist_list_item) );
  1211.         if ( chl == 0 )
  1212.             {
  1213.             (void) fprintf(
  1214.             stderr, "%s: out of memory computing hash table\n",
  1215.             progname );
  1216.             ppm_freecolorhash( cht );
  1217.             return (colorhash_table) 0;
  1218.             }
  1219.         chl->ch.color = *pP;
  1220.         chl->ch.value = 1;
  1221.         chl->next = cht[hash];
  1222.         cht[hash] = chl;
  1223.         }
  1224.         }
  1225.     
  1226.     return cht;
  1227.     }
  1228.  
  1229. colorhash_table
  1230. ppm_alloccolorhash( )
  1231.     {
  1232.     colorhash_table cht;
  1233.     int i;
  1234.  
  1235.     cht = (colorhash_table) malloc( HASH_SIZE * sizeof(colorhist_list) );
  1236.     if ( cht == 0 )
  1237.     {
  1238.     (void) fprintf(
  1239.         stderr, "%s: out of memory allocating hash table\n", progname );
  1240.     return (colorhash_table) 0;
  1241.     }
  1242.  
  1243.     for ( i = 0; i < HASH_SIZE; ++i )
  1244.     cht[i] = (colorhist_list) 0;
  1245.  
  1246.     return cht;
  1247.     }
  1248.  
  1249. int
  1250. ppm_addtocolorhash( cht, colorP, value )
  1251.     colorhash_table cht;
  1252.     pixel* colorP;
  1253.     int value;
  1254.     {
  1255.     register int hash;
  1256.     register colorhist_list chl;
  1257.  
  1258.     chl = (colorhist_list) malloc( sizeof(struct colorhist_list_item) );
  1259.     if ( chl == 0 )
  1260.     return -1;
  1261.     hash = ppm_hashpixel( *colorP );
  1262.     chl->ch.color = *colorP;
  1263.     chl->ch.value = value;
  1264.     chl->next = cht[hash];
  1265.     cht[hash] = chl;
  1266.     return 0;
  1267.     }
  1268.  
  1269. colorhist_vector
  1270. ppm_colorhashtocolorhist( cht, maxcolors )
  1271.     colorhash_table cht;
  1272.     int maxcolors;
  1273.     {
  1274.     colorhist_vector chv;
  1275.     colorhist_list chl;
  1276.     int i, j;
  1277.  
  1278.     /* Now collate the hash table into a simple colorhist array. */
  1279.     chv = (colorhist_vector) malloc( maxcolors * sizeof(struct colorhist_item) );
  1280.     /* (Leave room for expansion by caller.) */
  1281.     if ( chv == (colorhist_vector) 0 )
  1282.     {
  1283.     (void) fprintf(
  1284.         stderr, "%s: out of memory generating histogram\n", progname );
  1285.     return (colorhist_vector) 0;
  1286.     }
  1287.  
  1288.     /* Loop through the hash table. */
  1289.     j = 0;
  1290.     for ( i = 0; i < HASH_SIZE; ++i )
  1291.     for ( chl = cht[i]; chl != (colorhist_list) 0; chl = chl->next )
  1292.         {
  1293.         /* Add the new entry. */
  1294.         chv[j] = chl->ch;
  1295.         ++j;
  1296.         }
  1297.  
  1298.     /* All done. */
  1299.     return chv;
  1300.     }
  1301.  
  1302. colorhash_table
  1303. ppm_colorhisttocolorhash( chv, colors )
  1304.     colorhist_vector chv;
  1305.     int colors;
  1306.     {
  1307.     colorhash_table cht;
  1308.     int i, hash;
  1309.     pixel color;
  1310.     colorhist_list chl;
  1311.  
  1312.     cht = ppm_alloccolorhash( );
  1313.     if ( cht == (colorhash_table) 0 )
  1314.     return (colorhash_table) 0;
  1315.  
  1316.     for ( i = 0; i < colors; ++i )
  1317.     {
  1318.     color = chv[i].color;
  1319.     hash = ppm_hashpixel( color );
  1320.     for ( chl = cht[hash]; chl != (colorhist_list) 0; chl = chl->next )
  1321.         if ( PPM_EQUAL( chl->ch.color, color ) )
  1322.         {
  1323.         (void) fprintf(
  1324.             stderr, "%s: same color found twice - %d %d %d\n", progname,
  1325.             PPM_GETR(color), PPM_GETG(color), PPM_GETB(color) );
  1326.         ppm_freecolorhash( cht );
  1327.         return (colorhash_table) 0;
  1328.         }
  1329.     chl = (colorhist_list) malloc( sizeof(struct colorhist_list_item) );
  1330.     if ( chl == (colorhist_list) 0 )
  1331.         {
  1332.         (void) fprintf( stderr, "%s: out of memory\n", progname );
  1333.         ppm_freecolorhash( cht );
  1334.         return (colorhash_table) 0;
  1335.         }
  1336.     chl->ch.color = color;
  1337.     chl->ch.value = i;
  1338.     chl->next = cht[hash];
  1339.     cht[hash] = chl;
  1340.     }
  1341.  
  1342.     return cht;
  1343.     }
  1344.  
  1345. int
  1346. ppm_lookupcolor( cht, colorP )
  1347.     colorhash_table cht;
  1348.     pixel* colorP;
  1349.     {
  1350.     int hash;
  1351.     colorhist_list chl;
  1352.  
  1353.     hash = ppm_hashpixel( *colorP );
  1354.     for ( chl = cht[hash]; chl != (colorhist_list) 0; chl = chl->next )
  1355.     if ( PPM_EQUAL( chl->ch.color, *colorP ) )
  1356.         return chl->ch.value;
  1357.  
  1358.     return -1;
  1359.     }
  1360.  
  1361. void
  1362. ppm_freecolorhist( chv )
  1363.     colorhist_vector chv;
  1364.     {
  1365.     free( (char*) chv );
  1366.     }
  1367.  
  1368. void
  1369. ppm_freecolorhash( cht )
  1370.     colorhash_table cht;
  1371.     {
  1372.     int i;
  1373.     colorhist_list chl, chlnext;
  1374.  
  1375.     for ( i = 0; i < HASH_SIZE; ++i )
  1376.     for ( chl = cht[i]; chl != (colorhist_list) 0; chl = chlnext )
  1377.         {
  1378.         chlnext = chl->next;
  1379.         free( (char*) chl );
  1380.         }
  1381.     free( (char*) cht );
  1382.     }
  1383.